<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>继承实现：探究 JS 常见的 6 种继承方式 | 悄悄的卷，然后卷死所有人</title>
    <meta name="description" content="这是一个奇怪的地方">
    <link rel="stylesheet" href="/blobview/assets/style.019f39fc.css">
    <link rel="modulepreload" href="/blobview/assets/Home.d05cdc04.js">
    <link rel="modulepreload" href="/blobview/assets/app.a4363fd4.js">
    <link rel="modulepreload" href="/blobview/assets/fe_secondary_Javascript_jicheng.md.1cd0c4dc.lean.js">
    <link rel="modulepreload" href="/blobview/assets/app.a4363fd4.js">
    <meta name="twitter:title" content="继承实现：探究 JS 常见的 6 种继承方式 | 悄悄的卷，然后卷死所有人">
    <meta property="og:title" content="继承实现：探究 JS 常见的 6 种继承方式 | 悄悄的卷，然后卷死所有人">
  </head>
  <body>
    <div id="app"><!--[--><div class="theme"><header class="nav-bar" data-v-675d8756><div class="sidebar-button" data-v-675d8756><svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class></path></svg></div><a class="nav-bar-title" href="/blobview/" aria-label="悄悄的卷，然后卷死所有人, back to home" data-v-675d8756 data-v-4a583abe><!----> 悄悄的卷，然后卷死所有人</a><div class="flex-grow" data-v-675d8756></div><div class="nav" data-v-675d8756><nav class="nav-links" data-v-675d8756 data-v-eab3edfe><!--[--><div class="item" data-v-eab3edfe><div class="nav-link" data-v-eab3edfe data-v-b8818f8c><a class="item" href="/blobview/" data-v-b8818f8c>Home <!----></a></div></div><div class="item" data-v-eab3edfe><div class="nav-dropdown-link" data-v-eab3edfe data-v-56bf3a3f><button class="button" data-v-56bf3a3f><span class="button-text" data-v-56bf3a3f>前端君</span><span class="right button-arrow" data-v-56bf3a3f></span></button><ul class="dialog" data-v-56bf3a3f><!--[--><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/secondary/interviews/network" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>面试八股文</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/algorithm" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>算法大卷</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/errormd/chrome插件开发指南" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>坑你太美</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe><div class="nav-dropdown-link" data-v-eab3edfe data-v-56bf3a3f><button class="button" data-v-56bf3a3f><span class="button-text" data-v-56bf3a3f>稀奇君</span><span class="right button-arrow" data-v-56bf3a3f></span></button><ul class="dialog" data-v-56bf3a3f><!--[--><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/secondary/interviews/network" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>web3</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe><div class="nav-link" data-v-eab3edfe data-v-b8818f8c><a class="item" href="/blobview/b" data-v-b8818f8c>杂谈君 <!----></a></div></div><!--]--><!----><!----></nav></div><!--[--><!--]--></header><aside class="sidebar" data-v-83e92a68><nav class="nav-links nav" data-v-83e92a68 data-v-eab3edfe><!--[--><div class="item" data-v-eab3edfe><div class="nav-link" data-v-eab3edfe data-v-b8818f8c><a class="item" href="/blobview/" data-v-b8818f8c>Home <!----></a></div></div><div class="item" data-v-eab3edfe><div class="nav-dropdown-link" data-v-eab3edfe data-v-56bf3a3f><button class="button" data-v-56bf3a3f><span class="button-text" data-v-56bf3a3f>前端君</span><span class="right button-arrow" data-v-56bf3a3f></span></button><ul class="dialog" data-v-56bf3a3f><!--[--><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/secondary/interviews/network" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>面试八股文</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/algorithm" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>算法大卷</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/errormd/chrome插件开发指南" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>坑你太美</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe><div class="nav-dropdown-link" data-v-eab3edfe data-v-56bf3a3f><button class="button" data-v-56bf3a3f><span class="button-text" data-v-56bf3a3f>稀奇君</span><span class="right button-arrow" data-v-56bf3a3f></span></button><ul class="dialog" data-v-56bf3a3f><!--[--><li class="dialog-item" data-v-56bf3a3f><div class="nav-dropdown-link-item" data-v-56bf3a3f data-v-bbc27490><a class="item" href="/blobview/fe/secondary/interviews/network" data-v-bbc27490><span class="arrow" data-v-bbc27490></span><span class="text" data-v-bbc27490>web3</span><span class="icon" data-v-bbc27490><!----></span></a></div></li><!--]--></ul></div></div><div class="item" data-v-eab3edfe><div class="nav-link" data-v-eab3edfe data-v-b8818f8c><a class="item" href="/blobview/b" data-v-b8818f8c>杂谈君 <!----></a></div></div><!--]--><!----><!----></nav><!--[--><!--]--><ul class="sidebar-links" data-v-83e92a68><!--[--><li class="sidebar-link"><a class="sidebar-link-item" href="#继承概念的探究">继承概念的探究</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#js-实现继承的几种方式">JS 实现继承的几种方式</a><ul class="sidebar-links"><li class="sidebar-link"><a class="sidebar-link-item" href="#第一种：原型链继承">第一种：原型链继承</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#第二种：构造函数继承（借助-call）">第二种：构造函数继承（借助 call）</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#第三种：组合继承（前两种组合）">第三种：组合继承（前两种组合）</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#第四种：原型式继承">第四种：原型式继承</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#第五种：寄生式继承">第五种：寄生式继承</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#第六种：寄生组合式继承">第六种：寄生组合式继承</a><!----></li><li class="sidebar-link"><a class="sidebar-link-item" href="#es6-的-extends-关键字实现逻辑">ES6 的 extends 关键字实现逻辑</a><!----></li></ul></li><li class="sidebar-link"><a class="sidebar-link-item" href="#总结">总结</a><!----></li><!--]--></ul><!--[--><!--]--></aside><div class="sidebar-mask"></div><main class="page" data-v-7eddb2c4><div class="container" data-v-7eddb2c4><!--[--><!--]--><div style="position:relative;" class="content" data-v-7eddb2c4><div><h1 id="继承实现：探究-js-常见的-6-种继承方式" tabindex="-1">继承实现：探究 JS 常见的 6 种继承方式 <a class="header-anchor" href="#继承实现：探究-js-常见的-6-种继承方式" aria-hidden="true">#</a></h1><p>这一讲我要带你一起探究 JavaScript 的继承方式。</p><p>我先来简单介绍一下继承的概念。继承是面向对象的，使用这种方式我们可以更好地复用以前的开发代码，缩短开发的周期、提升开发效率。</p><p>继承在各种编程语言中都充当着至关重要的角色，特别是在 JavaScript 中，它天生的灵活性，使应用场景更加丰富。JavaScript 的继承也经常会在用在前端工程基础库的底层搭建上面，在整个 JavaScript 的学习中尤为重要。</p><p>因此，我希望这一讲，能让你对 JavaScript 的继承有更深一步的理解，更加得心应手地运用在业务代码中，并可以轻松掌握和 JavaScript 继承相关的面试题目。</p><p>那么，为了方便你更好地理解本讲的内容，在课程开始前请你先思考几个问题：</p><ul><li><p>JS 的继承到底有多少种实现方式呢？</p></li><li><p>ES6 的 extends 关键字是用哪种继承方式实现的呢？</p></li></ul><p>是不是这几个问题并不是那么容易地回答出来？那么我们带着思考，开始学习。</p><h2 id="继承概念的探究" tabindex="-1">继承概念的探究 <a class="header-anchor" href="#继承概念的探究" aria-hidden="true">#</a></h2><p>说到继承的概念，首先要说一个经典的例子。</p><p>先定义一个类（Class）叫汽车，汽车的属性包括颜色、轮胎、品牌、速度、排气量等，由汽车这个类可以派生出“轿车”和“货车”两个类，那么可以在汽车的基础属性上，为轿车添加一个后备厢、给货车添加一个大货箱。这样轿车和货车就是不一样的，但是二者都属于汽车这个类，这样从这个例子中就能详细说明汽车、轿车以及卡车之间的继承关系。</p><p>继承可以使得子类别具有父类的各种方法和属性，比如上面的例子中“轿车” 和 “货车” 分别继承了汽车的属性，而不需要再次在“轿车”中定义汽车已经有的属性。在“轿车”继承“汽车”的同时，也可以重新定义汽车的某些属性，并重写或覆盖某些属性和方法，使其获得与“汽车”这个父类不同的属性和方法。</p><p>继承的基本概念就初步介绍这些，下面我们就来看看 JavaScript 中都有哪些实现继承的方法。</p><h2 id="js-实现继承的几种方式" tabindex="-1">JS 实现继承的几种方式 <a class="header-anchor" href="#js-实现继承的几种方式" aria-hidden="true">#</a></h2><h3 id="第一种：原型链继承" tabindex="-1">第一种：原型链继承 <a class="header-anchor" href="#第一种：原型链继承" aria-hidden="true">#</a></h3><p>原型链继承是比较常见的继承方式之一，其中涉及的构造函数、原型和实例，三者之间存在着一定的关系，即每一个构造函数都有一个原型对象，原型对象又包含一个指向构造函数的指针，而实例则包含一个原型对象的指针。</p><p>下面我们结合代码来了解一下。</p><div class="language-js"><pre><code>  <span class="token keyword">function</span> <span class="token function">Parent1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">&#39;parent1&#39;</span><span class="token punctuation">;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>play <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span>

  <span class="token punctuation">}</span>

  <span class="token keyword">function</span> <span class="token function">Child1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>type <span class="token operator">=</span> <span class="token string">&#39;child2&#39;</span><span class="token punctuation">;</span>

  <span class="token punctuation">}</span>

  <span class="token class-name">Child1</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Parent1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">Child1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

</code></pre></div><p>上面的代码看似没有问题，虽然父类的方法和属性都能够访问，但其实有一个潜在的问题，我再举个例子来说明这个问题。</p><div class="language-js"><pre><code>  <span class="token keyword">var</span> s1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">var</span> s2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  s1<span class="token punctuation">.</span>play<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>s1<span class="token punctuation">.</span>play<span class="token punctuation">,</span> s2<span class="token punctuation">.</span>play<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token operator">&lt;</span><span class="token operator">!</span><span class="token operator">--</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">]</span>  <span class="token operator">--</span><span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span><span class="token operator">!</span><span class="token operator">--</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">]</span>  <span class="token operator">--</span><span class="token operator">&gt;</span>
</code></pre></div><p>明明我只改变了 s1 的 play 属性，为什么 s2 也跟着变了呢？原因很简单，因为两个实例使用的是同一个原型对象。它们的内存空间是共享的，当一个发生变化的时候，另外一个也随之进行了变化，这就是使用原型链继承方式的一个缺点。</p><p>那么要解决这个问题的话，我们就得再看看其他的继承方式，下面我们看看能解决原型属性共享问题的第二种方法。</p><h3 id="第二种：构造函数继承（借助-call）" tabindex="-1">第二种：构造函数继承（借助 call） <a class="header-anchor" href="#第二种：构造函数继承（借助-call）" aria-hidden="true">#</a></h3><div class="language-js"><pre><code>  <span class="token keyword">function</span> <span class="token function">Parent1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">&#39;parent1&#39;</span><span class="token punctuation">;</span>

  <span class="token punctuation">}</span>

  <span class="token class-name">Parent1</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">getName</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token punctuation">;</span>

  <span class="token punctuation">}</span>


  <span class="token keyword">function</span> <span class="token function">Child1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>

    <span class="token function">Parent1</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>type <span class="token operator">=</span> <span class="token string">&#39;child1&#39;</span>

  <span class="token punctuation">}</span>

  <span class="token keyword">let</span> child <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child1</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// 没问题</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// 会报错</span>

</code></pre></div><p>执行上面的这段代码，可以得到这样的结果。</p><p><img src="https://mziname.oss-cn-beijing.aliyuncs.com/images/CgpVE1_9B-qAHGGjAABBe0l-7oE835.png" alt="code"></p><p>可以看到最后打印的 child 在控制台显示，除了 Child1 的属性 type 之外，也继承了 Parent1 的属性 name。这样写的时候子类虽然能够拿到父类的属性值，解决了第一种继承方式的弊端，但问题是，父类原型对象中一旦存在父类之前自己定义的方法，那么子类将无法继承这些方法。这种情况的控制台执行结果如下图所示。</p><p><img src="https://mziname.oss-cn-beijing.aliyuncs.com/images/Ciqc1F_9B_KACrgnAABDSFXfnx0666.png" alt="codeerror"></p><p>因此，从上面的结果就可以看到构造函数实现继承的优缺点，它使父类的引用属性不会被共享，优化了第一种继承方式的弊端；但是随之而来的缺点也比较明显——只能继承父类的实例属性和方法，不能继承原型属性或者方法。</p><h3 id="第三种：组合继承（前两种组合）" tabindex="-1">第三种：组合继承（前两种组合） <a class="header-anchor" href="#第三种：组合继承（前两种组合）" aria-hidden="true">#</a></h3><p>这种方式结合了前两种继承方式的优缺点，结合起来的继承，代码如下。</p><div class="language-js"><pre><code>  <span class="token keyword">function</span> <span class="token function">Parent3</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">&#39;parent3&#39;</span><span class="token punctuation">;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>play <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token punctuation">}</span>

  <span class="token class-name">Parent3</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">getName</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token punctuation">;</span>

  <span class="token punctuation">}</span>

  <span class="token keyword">function</span> <span class="token function">Child3</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 第二次调用 Parent3()</span>
    <span class="token function">Parent3</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>type <span class="token operator">=</span> <span class="token string">&#39;child3&#39;</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token comment">// 第一次调用 Parent3()</span>
  <span class="token class-name">Child3</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Parent3</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 手动挂上构造器，指向自己的构造函数</span>
  <span class="token class-name">Child3</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> Child3<span class="token punctuation">;</span>

  <span class="token keyword">var</span> s3 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child3</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">var</span> s4 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child3</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  s3<span class="token punctuation">.</span>play<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>s3<span class="token punctuation">.</span>play<span class="token punctuation">,</span> s4<span class="token punctuation">.</span>play<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// 不互相影响</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>s3<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 正常输出&#39;parent3&#39;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>s4<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 正常输出&#39;parent3&#39;</span>

</code></pre></div><p>执行上面的代码，可以看到控制台的输出结果，之前方法一和方法二的问题都得以解决。</p><div class="language-js"><pre><code><span class="token comment">// [1,2,3,4]</span>
<span class="token comment">// [1,2,3]</span>
<span class="token comment">// parents3</span>
<span class="token comment">// parents3</span>
</code></pre></div><p>但是这里又增加了一个新问题：通过注释我们可以看到 Parent3 执行了两次，第一次是改变Child3 的 prototype 的时候，第二次是通过 call 方法调用 Parent3 的时候，那么 Parent3 多构造一次就多进行了一次性能开销，这是我们不愿看到的。</p><p>那么是否有更好的办法解决这个问题呢？请你再往下学习，下面的第六种继承方式可以更好地解决这里的问题。</p><p>上面介绍的更多是围绕着构造函数的方式，那么对于 JavaScript 的普通对象，怎么实现继承呢？</p><h3 id="第四种：原型式继承" tabindex="-1">第四种：原型式继承 <a class="header-anchor" href="#第四种：原型式继承" aria-hidden="true">#</a></h3><p>这里不得不提到的就是 ES5 里面的 Object.create 方法，这个方法接收两个参数：一是用作新对象原型的对象、二是为新对象定义额外属性的对象（可选参数）。</p><p>我们通过一段代码，看看普通对象是怎么实现的继承。</p><div class="language-js"><pre><code>  <span class="token keyword">let</span> parent4 <span class="token operator">=</span> <span class="token punctuation">{</span>

    name<span class="token operator">:</span> <span class="token string">&quot;parent4&quot;</span><span class="token punctuation">,</span>

    friends<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;p1&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;p2&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;p3&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>

    <span class="token function-variable function">getName</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token punctuation">;</span>

    <span class="token punctuation">}</span>

  <span class="token punctuation">}</span><span class="token punctuation">;</span>



  <span class="token keyword">let</span> person4 <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>parent4<span class="token punctuation">)</span><span class="token punctuation">;</span>

  person4<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">&quot;tom&quot;</span><span class="token punctuation">;</span>

  person4<span class="token punctuation">.</span>friends<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token string">&quot;jerry&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>



  <span class="token keyword">let</span> person5 <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>parent4<span class="token punctuation">)</span><span class="token punctuation">;</span>

  person5<span class="token punctuation">.</span>friends<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token string">&quot;lucy&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>



  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person4<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person4<span class="token punctuation">.</span>name <span class="token operator">===</span> person4<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person5<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person4<span class="token punctuation">.</span>friends<span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person5<span class="token punctuation">.</span>friends<span class="token punctuation">)</span><span class="token punctuation">;</span>

</code></pre></div><p>从上面的代码中可以看到，通过 Object.create 这个方法可以实现普通对象的继承，不仅仅能继承属性，同样也可以继承 getName 的方法，请看这段代码的执行结果。</p><p><img src="https://mziname.oss-cn-beijing.aliyuncs.com/images/CgqCHl_9CASAJMvwAAA_d30-jH8783.png" alt="code1"></p><p>第一个结果“tom”，比较容易理解，person4 继承了 parent4 的 name 属性，但是在这个基础上又进行了自定义。</p><p>第二个是继承过来的 getName 方法检查自己的 name 是否和属性里面的值一样，答案是 true。</p><p>第三个结果“parent4”也比较容易理解，person5 继承了 parent4 的 name 属性，没有进行覆盖，因此输出父对象的属性。</p><p>最后两个输出结果是一样的，讲到这里你应该可以联想到 02 讲中浅拷贝的知识点，关于引用数据类型“共享”的问题，其实 Object.create 方法是可以为一些对象实现浅拷贝的。</p><p>那么关于这种继承方式的缺点也很明显，多个实例的引用类型属性指向相同的内存，存在篡改的可能，接下来我们看一下在这个继承基础上进行优化之后的另一种继承方式——寄生式继承。</p><h3 id="第五种：寄生式继承" tabindex="-1">第五种：寄生式继承 <a class="header-anchor" href="#第五种：寄生式继承" aria-hidden="true">#</a></h3><p>使用原型式继承可以获得一份目标对象的浅拷贝，然后利用这个浅拷贝的能力再进行增强，添加一些方法，这样的继承方式就叫作寄生式继承。</p><p>虽然其优缺点和原型式继承一样，但是对于普通对象的继承方式来说，寄生式继承相比于原型式继承，还是在父类基础上添加了更多的方法。那么我们看一下代码是怎么实现。</p><div class="language-js"><pre><code>   <span class="token keyword">let</span> parent5 <span class="token operator">=</span> <span class="token punctuation">{</span>

    name<span class="token operator">:</span> <span class="token string">&quot;parent5&quot;</span><span class="token punctuation">,</span>

    friends<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">&quot;p1&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;p2&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;p3&quot;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>

    <span class="token function-variable function">getName</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token punctuation">;</span>

    <span class="token punctuation">}</span>

  <span class="token punctuation">}</span><span class="token punctuation">;</span>

  <span class="token keyword">function</span> <span class="token function">clone</span><span class="token punctuation">(</span><span class="token parameter">original</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">let</span> clone <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>original<span class="token punctuation">)</span><span class="token punctuation">;</span>

    clone<span class="token punctuation">.</span><span class="token function-variable function">getFriends</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

      <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>friends<span class="token punctuation">;</span>

    <span class="token punctuation">}</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> clone<span class="token punctuation">;</span>

  <span class="token punctuation">}</span>

  <span class="token keyword">let</span> person5 <span class="token operator">=</span> <span class="token function">clone</span><span class="token punctuation">(</span>parent5<span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person5<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person5<span class="token punctuation">.</span><span class="token function">getFriends</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

</code></pre></div><p>通过上面这段代码，我们可以看到 person5 是通过寄生式继承生成的实例，它不仅仅有 getName 的方法，而且可以看到它最后也拥有了 getFriends 的方法，结果如下图所示。</p><div class="language-js"><pre><code><span class="token comment">// parent5</span>
<span class="token comment">// [&#39;p1&#39;,&#39;p2&#39;,&#39;p3&#39;]</span>
</code></pre></div><p>从最后的输出结果中可以看到，person5 通过 clone 的方法，增加了 getFriends 的方法，从而使 person5 这个普通对象在继承过程中又增加了一个方法，这样的继承方式就是寄生式继承。</p><p>我在上面第三种组合继承方式中提到了一些弊端，即两次调用父类的构造函数造成浪费，下面要介绍的寄生组合继承就可以解决这个问题。</p><h3 id="第六种：寄生组合式继承" tabindex="-1">第六种：寄生组合式继承 <a class="header-anchor" href="#第六种：寄生组合式继承" aria-hidden="true">#</a></h3><p>结合第四种中提及的继承方式，解决普通对象的继承问题的 Object.create 方法，我们在前面这几种继承方式的优缺点基础上进行改造，得出了寄生组合式的继承方式，这也是所有继承方式里面相对最优的继承方式，代码如下</p><div class="language-js"><pre><code>  <span class="token keyword">function</span> <span class="token function">clone</span> <span class="token punctuation">(</span><span class="token parameter">parent<span class="token punctuation">,</span> child</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 这里改用 Object.create 就可以减少组合继承中多进行一次构造的过程</span>
    child<span class="token punctuation">.</span>prototype <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span><span class="token punctuation">;</span>

    child<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> child<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token keyword">function</span> <span class="token function">Parent6</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">&#39;parent6&#39;</span><span class="token punctuation">;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>play <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

   <span class="token class-name">Parent6</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">getName</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token punctuation">;</span>

  <span class="token punctuation">}</span>

  <span class="token keyword">function</span> <span class="token function">Child6</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">Parent6</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>friends <span class="token operator">=</span> <span class="token string">&#39;child5&#39;</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token function">clone</span><span class="token punctuation">(</span>Parent6<span class="token punctuation">,</span> Child6<span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token class-name">Child6</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">getFriends</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>friends<span class="token punctuation">;</span>

  <span class="token punctuation">}</span>

  <span class="token keyword">let</span> person6 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child6</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person6<span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person6<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>person6<span class="token punctuation">.</span><span class="token function">getFriends</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

</code></pre></div><p>通过这段代码可以看出来，这种寄生组合式继承方式，基本可以解决前几种继承方式的缺点，较好地实现了继承想要的结果，同时也减少了构造次数，减少了性能的开销，我们来看一下上面这一段代码的执行结果。</p><p><img src="https://mziname.oss-cn-beijing.aliyuncs.com/images/CgqCHl_9CBWATQbEAABszTJIdBQ249.png" alt="image"></p><p>可以看到 person6 打印出来的结果，属性都得到了继承，方法也没问题，可以输出预期的结果。</p><p>整体看下来，这六种继承方式中，寄生组合式继承是这六种里面最优的继承方式。另外，ES6 还提供了继承的关键字 extends，我们再看下 extends 的底层实现继承的逻辑。</p><h3 id="es6-的-extends-关键字实现逻辑" tabindex="-1">ES6 的 extends 关键字实现逻辑 <a class="header-anchor" href="#es6-的-extends-关键字实现逻辑" aria-hidden="true">#</a></h3><p>我们可以利用 ES6 里的 extends 的语法糖，使用关键词很容易直接实现 JavaScript 的继承，但是如果想深入了解 extends 语法糖是怎么实现的，就得深入研究 extends 的底层逻辑。</p><p>我们先看下用利用 extends 如何直接实现继承，代码如下。</p><div class="language-js"><pre><code><span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name
  <span class="token punctuation">}</span>
  <span class="token comment">// 原型方法</span>

  <span class="token comment">// 即 Person.prototype.getName = function() { }</span>

  <span class="token comment">// 下面可以简写为 getName() {...}</span>

  <span class="token function-variable function">getName</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&#39;Person:&#39;</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Gamer</span> <span class="token keyword">extends</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>

  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">name<span class="token punctuation">,</span> age</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 子类中存在构造函数，则需要在使用“this”之前首先调用 super()。</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age
  <span class="token punctuation">}</span>

<span class="token punctuation">}</span>
<span class="token keyword">const</span> asuna <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Gamer</span><span class="token punctuation">(</span><span class="token string">&#39;Asuna&#39;</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">)</span>

asuna<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 成功访问到父类的方法</span>

</code></pre></div><p>因为浏览器的兼容性问题，如果遇到不支持 ES6 的浏览器，那么就得利用 babel 这个编译工具，将 ES6 的代码编译成 ES5，让一些不支持新语法的浏览器也能运行。</p><p>那么最后 extends 编译成了什么样子呢？我们看一下转译之后的代码片段。</p><div class="language-js"><pre><code><span class="token keyword">function</span> <span class="token function">_possibleConstructorReturn</span> <span class="token punctuation">(</span><span class="token parameter">self<span class="token punctuation">,</span> call</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 
		<span class="token comment">// ...</span>
		<span class="token keyword">return</span> call <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> call <span class="token operator">===</span> <span class="token string">&#39;object&#39;</span> <span class="token operator">||</span> <span class="token keyword">typeof</span> call <span class="token operator">===</span> <span class="token string">&#39;function&#39;</span><span class="token punctuation">)</span> <span class="token operator">?</span> call <span class="token operator">:</span> self<span class="token punctuation">;</span> 
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_inherits</span> <span class="token punctuation">(</span><span class="token parameter">subClass<span class="token punctuation">,</span> superClass</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 
    <span class="token comment">// 这里可以看到</span>
	subClass<span class="token punctuation">.</span>prototype <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>superClass <span class="token operator">&amp;&amp;</span> superClass<span class="token punctuation">.</span>prototype<span class="token punctuation">,</span> <span class="token punctuation">{</span> 

		constructor<span class="token operator">:</span> <span class="token punctuation">{</span> 

			value<span class="token operator">:</span> subClass<span class="token punctuation">,</span> 

			enumerable<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span> 

			writable<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> 

			configurable<span class="token operator">:</span> <span class="token boolean">true</span> 

		<span class="token punctuation">}</span> 
	<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
	<span class="token keyword">if</span> <span class="token punctuation">(</span>superClass<span class="token punctuation">)</span> Object<span class="token punctuation">.</span>setPrototypeOf <span class="token operator">?</span> Object<span class="token punctuation">.</span><span class="token function">setPrototypeOf</span><span class="token punctuation">(</span>subClass<span class="token punctuation">,</span> superClass<span class="token punctuation">)</span> <span class="token operator">:</span> subClass<span class="token punctuation">.</span>__proto__ <span class="token operator">=</span> superClass<span class="token punctuation">;</span> 
<span class="token punctuation">}</span>

<span class="token keyword">var</span> <span class="token function-variable function">Parent</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">Parent</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

	<span class="token comment">// 验证是否是 Parent 构造出来的 this</span>

	<span class="token function">_classCallCheck</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> Parent<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> Child <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">_Parent</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

	<span class="token function">_inherits</span><span class="token punctuation">(</span>Child<span class="token punctuation">,</span> _Parent<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token keyword">function</span> <span class="token function">Child</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

		<span class="token function">_classCallCheck</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> Child<span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token keyword">return</span> <span class="token function">_possibleConstructorReturn</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token punctuation">(</span>Child<span class="token punctuation">.</span>__proto__ <span class="token operator">||</span> Object<span class="token punctuation">.</span><span class="token function">getPrototypeOf</span><span class="token punctuation">(</span>Child<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token punctuation">}</span>

	<span class="token keyword">return</span> Child<span class="token punctuation">;</span>

<span class="token punctuation">}</span><span class="token punctuation">(</span>Parent<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

</code></pre></div><p>从上面编译完成的源码中可以看到，它采用的也是寄生组合继承方式，因此也证明了这种方式是较优的解决继承的方式。</p><p>到这里，JavaScript 中实现继承的方式也基本讲解差不多了，本课时也将告一段落。</p><h2 id="总结" tabindex="-1">总结 <a class="header-anchor" href="#总结" aria-hidden="true">#</a></h2><p>下面我将 JavaScript 的继承方式做了个总结的脑图，方便你更清晰地回顾本课时所讲的内容。</p><p><img src="https://mziname.oss-cn-beijing.aliyuncs.com/images/Ciqc1F_9SVuAfHXWAAEfwyAfiC0647.png" alt="img"></p><p>通过 Object.create 来划分不同的继承方式，最后的寄生式组合继承方式是通过组合继承改造之后的最优继承方式，而 extends 的语法糖和寄生组合继承的方式基本类似。</p><p>综上，我们可以看到不同的继承方式有不同的优缺点，我们需要深入了解各种方式的优缺点，这样才能在日常开发中，选择最适合当前场景的继承方式。</p><p>在日常的前端开发工作中，开发者往往会忽视对继承相关的系统性学习，但因为继承的方法比较多，每个实现的方法细节也比较零散，很多开发者很难有一个系统的、整体的认识，造成效率低下，以及代码能力难以进一步提升等问题。</p></div></div><footer class="page-footer" data-v-7eddb2c4 data-v-fb8d84c6><div class="edit" data-v-fb8d84c6><div class="edit-link" data-v-fb8d84c6 data-v-1ed99556><!----></div></div><div class="updated" data-v-fb8d84c6><!----></div></footer><!----><!--[--><!--]--></div></main></div><!----><!--]--></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"fe_algorithm.md\":\"e1054222\",\"fe_errormd_chrome插件开发指南.md\":\"8310a77a\",\"fe_errormd_mysql密码遗忘.md\":\"37b8860e\",\"fe_secondary_javascript_descriptors.md\":\"cd9a7474\",\"fe_secondary_javascript_javascript.md\":\"42853649\",\"fe_secondary_javascript_jicheng.md\":\"1cd0c4dc\",\"fe_secondary_javascript_jscopy.md\":\"66795111\",\"fe_secondary_javascript_js数据类型.md\":\"c6bc851f\",\"fe_secondary_javascript_let const var 的区别.md\":\"685e3545\",\"fe_secondary_javascript_weakmap.md\":\"2a0ba820\",\"fe_secondary_javascript_作用域.md\":\"220cfcf9\",\"fe_secondary_javascript_变量提升.md\":\"b63f20ee\",\"fe_secondary_javascript_闭包.md\":\"5404cbcf\",\"fe_secondary_python_基础知识.md\":\"ae39dc27\",\"fe_secondary_vite_vite杂烩记录.md\":\"aa7cf9a4\",\"fe_secondary_webpack_loader与plugin的不同.md\":\"e2712a7c\",\"fe_secondary_interviews_jstype.md\":\"b3e700ba\",\"fe_secondary_interviews_mianshi.md\":\"218f21c3\",\"fe_secondary_interviews_modular.md\":\"38434f4f\",\"fe_secondary_interviews_network.md\":\"d5842ea6\",\"fe_suanfa_tree树结构.md\":\"d41c852f\",\"fe_suanfa_二分查找.md\":\"28f745d1\",\"fe_suanfa_二叉树.md\":\"836f7969\",\"fe_suanfa_二叉树后序遍历.md\":\"af43c381\",\"fe_suanfa_二叉树展开链表.md\":\"cc410293\",\"fe_suanfa_二叉树最小深度.md\":\"d272316f\",\"fe_suanfa_二叉树的所有路径.md\":\"70f2feac\",\"fe_suanfa_二叉树的最大深度.md\":\"ab1fe25c\",\"fe_suanfa_冒泡排序.md\":\"b91ecca4\",\"fe_suanfa_前中后序遍历.md\":\"997426ab\",\"fe_suanfa_前缀和.md\":\"6ec90ae8\",\"fe_suanfa_区域和检索数组不可变.md\":\"6e447cdb\",\"fe_suanfa_反转数组.md\":\"c28c7d5f\",\"fe_suanfa_将有序数组转换为二叉搜索树.md\":\"6a79c21d\",\"fe_suanfa_差分.md\":\"101d6b54\",\"fe_suanfa_快速排序.md\":\"575fe1af\",\"fe_suanfa_插入排序.md\":\"078511c5\",\"fe_suanfa_滑动窗口.md\":\"08f684ff\",\"fe_suanfa_翻转二叉树.md\":\"1a866015\",\"fe_suanfa_选择排序.md\":\"a25eac11\",\"fe_suanfa_链表反转.md\":\"a642cc7a\",\"fe_web3_ethers_01-hellovitalik.md\":\"162c31f8\",\"fe_web3_ethers_02-合约交互.md\":\"08f30902\",\"fe_web3_ethers_03-发送eth.md\":\"fbf8825d\",\"index.md\":\"64947f2b\"}")</script>
    <script type="module" async src="/blobview/assets/app.a4363fd4.js"></script>
    
  </body>
</html>